﻿using Learun.Util;
using Learun.Util.SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Learun.Application.TwoDevelopment.ZZDT_EC
{
    /// <summary>
    /// 版 本 PIT-ADMS V7.0.3 敏捷开发框架
    /// Copyright (c) 2013-2018 Hexagon PPM
    /// 创 建：超级管理员
    /// 日 期：2022-02-24 11:12
    /// 描 述：对象类型属性表
    /// </summary>
    public class ec_objecttypepService
    {
        #region 仓储
        Repository<ec_projectEntity> _projectRepository => new Repository<ec_projectEntity>();
        Repository<ec_objecttypepEntity> _objecttypepRepository => new Repository<ec_objecttypepEntity>();
        Repository<ec_propertyEntity> _propertyRepository => new Repository<ec_propertyEntity>();
        Repository<ec_measuring_unitEntity> _unitRepository => new Repository<ec_measuring_unitEntity>();
        Repository<ec_enginedataEntity> _enginedataRepository => new Repository<ec_enginedataEntity>();
        Repository<ec_enginedata_propertyEntity> _enginedataPropertyRepository => new Repository<ec_enginedata_propertyEntity>();
        #endregion
        #region 获取数据
        /// <summary>
        /// 获取对象类型属性表数据。要注意，如果objectTypeID是“”，则是查询全部的
        /// <summary>
        /// <param name="objectTypeID">对象类型ID。多个对象类型以逗号风格。如果是“”，则是查询全部的</param>
        /// <param name="ProjectId">项目ID</param>
        /// <param name="isLoadExtraData">是否加载额外的数据</param>
        /// <returns></returns>
        public IEnumerable<ec_objecttypepEntity> GetObjectTypePById(string objectTypeID, string ProjectId, bool isLoadExtraData = false)
        {
            try
            {
                var ProjectEntity = new ec_projectEntity();
                if (!string.IsNullOrWhiteSpace(ProjectId))
                {
                    ProjectEntity = _projectRepository.GetById(ProjectId);
                }
                var strSql = new StringBuilder();
                strSql.Append(@" SELECT t1.* ");
                if (isLoadExtraData)
                {
                    strSql.Append(@" ,t2.PropertyName
                                     ,t2.PropertyNameEN
                                     ,t2.PropertyType
                                     ,t2.DecimalPoint
                                     ,t2.EnumData
                                     ,t3.PropertyGroupName
                                     ,t3.PropertyGID
                                     ,t2.MeasuringUnitTypeID
                                     ,t2.DefaultUnit
                                     ,t2.DefaultValue
                                     ,t4.MeasuringUnitTypeName AS MeasuringUnitTypeName
                                     ,t5.MeasuringUnitName AS DefaultUnitName
                                     ,T2.BasicGroup");
                    if (string.IsNullOrWhiteSpace(ProjectId))
                    {
                        strSql.Append(" ,(select GROUP_CONCAT(st1.DataItemName SEPARATOR ',') from ec_dataitemdetail st1 where st1.DataItemID IN (SELECT sst1.DataItemID FROM ec_dataitem sst1 WHERE sst1.DataItemCode= t2.EnumData) and st1.IsEnabled=1 ORDER BY st1.OrderID) as EnumDataCode ");
                    }
                    else
                    {
                        strSql.Append($" ,(select GROUP_CONCAT(st1.DataItemName SEPARATOR ',') from ec_dataitemdetail_{ProjectEntity.ProjectIndex} st1 where st1.DataItemID IN (SELECT sst1.DataItemID FROM ec_dataitem_{ProjectEntity.ProjectIndex} sst1 WHERE sst1.DataItemCode= t2.EnumData) and st1.IsEnabled=1 ORDER BY st1.OrderID) as EnumDataCode ");
                    }
                }
                if (string.IsNullOrWhiteSpace(ProjectId))
                {
                    strSql.Append($" FROM ec_objecttypep t1 ");
                    if (isLoadExtraData)
                    {
                        strSql.Append($" INNER JOIN ec_property t2 ON t2.PropertyID = t1.PropertyID ");
                        strSql.Append($" INNER JOIN ec_propertyg t3 ON t3.PropertyGID = t2.PropertyGID ");
                        strSql.Append(@" LEFT JOIN ec_measuring_unittype t4 ON t2.MeasuringUnitTypeID = t4.MeasuringUnitTypeID
                                         LEFT JOIN ec_measuring_unit t5 ON t2.DefaultUnit = t5.MeasuringUnitID");
                    }
                }
                else
                {
                    strSql.Append($" FROM ec_objecttypep_{ProjectEntity.ProjectIndex} t1 ");
                    if (isLoadExtraData)
                    {
                        strSql.Append($" INNER JOIN ec_property_{ProjectEntity.ProjectIndex} t2 ON t2.PropertyID = t1.PropertyID ");
                        strSql.Append($" INNER JOIN ec_propertyg_{ProjectEntity.ProjectIndex} t3 ON t3.PropertyGID = t2.PropertyGID ");
                        strSql.Append($@" LEFT JOIN ec_measuring_unittype_{ProjectEntity.ProjectIndex} t4 ON t2.MeasuringUnitTypeID = t4.MeasuringUnitTypeID
                                          LEFT JOIN ec_measuring_unit_{ProjectEntity.ProjectIndex} t5 ON t2.DefaultUnit = t5.MeasuringUnitID");
                    }
                }
                strSql.Append(" WHERE 1=1 ");
                if (!string.IsNullOrEmpty(objectTypeID))
                {
                    if (objectTypeID.Contains(","))
                    {
                        List<string> ids = objectTypeID.Split(',').ToList();
                        string strWhere = string.Join(",", (from tb in ids select "'" + tb + "'").ToList());
                        strSql.Append($" AND t1.ObjectTypeID IN ({strWhere}) ");
                    }
                    else
                    {
                        strSql.Append($" AND t1.ObjectTypeID = '{objectTypeID}' ");
                    }
                }
                if (isLoadExtraData)
                {
                    strSql.Append($" ORDER BY t3.OrderID, t2.OrderID");
                }
                //return this.BaseRepository().FindList<ec_objecttypepEntity>(strSql.ToString());
                var res =  SqlSugarHelper.Db.SqlQueryable<ec_objecttypepEntity>(strSql.ToString()).ToList();

                return res;
            }
            catch (Exception ex)
            {
                if (ex is ExceptionEx)
                {
                    throw;
                }
                else
                {
                    throw ExceptionEx.ThrowBusinessException(ex);
                }
            }
        }

        /// <summary>
        /// 获取属性反向关联的对象类型表数据
        /// <summary>
        /// <param name="propertyID">属性ID</param>
        /// <param name="ProjectId">项目ID</param>
        /// <returns></returns>
        public IEnumerable<ec_objecttypepEntity> GetPropertyByObjectId(string propertyID, string ProjectId)
        {
            try
            {
                var ProjectEntity = new ec_projectEntity();
                if (!string.IsNullOrWhiteSpace(ProjectId))
                {
                    ProjectEntity = _projectRepository.GetById(ProjectId);
                }
                var strSql = new StringBuilder();
                strSql.Append(@" SELECT t1.* ");
                if (string.IsNullOrWhiteSpace(ProjectId))
                {
                    strSql.Append($" FROM ec_objecttypep t1 ");
                }
                else
                {
                    strSql.Append($" FROM ec_objecttypep_{ProjectEntity.ProjectIndex} t1 ");
                }
                strSql.Append(" WHERE 1=1 ");
                if (!string.IsNullOrEmpty(propertyID))
                {
                    if (propertyID.Contains(","))
                    {
                        List<string> ids = propertyID.Split(',').ToList();
                        string strWhere = string.Join(",", (from tb in ids select "'" + tb + "'").ToList());
                        strSql.Append($" AND t1.PropertyID IN ({strWhere}) ");
                    }
                    else
                    {
                        strSql.Append($" AND t1.PropertyID = '{propertyID}' ");
                    }
                }
                //return this.BaseRepository().FindList<ec_objecttypepEntity>(strSql.ToString());
                return SqlSugarHelper.Db.SqlQueryable<ec_objecttypepEntity>(strSql.ToString()).ToList();
            }
            catch (Exception ex)
            {
                if (ex is ExceptionEx)
                {
                    throw;
                }
                else
                {
                    throw ExceptionEx.ThrowBusinessException(ex);
                }
            }
        }

        #endregion

        #region 提交数据
        /// <summary>
        /// 删除实体数据
        /// <param name="keyValue">主键</param>
        /// <summary>
        /// <returns></returns>
        public void DeleteEntity(string keyValue, string ProjectId)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(ProjectId))
                {
                    _objecttypepRepository.Delete(t => t.ObjectTypePID == keyValue);
                }
                else
                {
                    var ProjectEntity = _projectRepository.GetById(ProjectId);
                    SqlSugarHelper.Db.Ado.ExecuteCommand($" DELETE FROM ec_objecttypep_{ProjectEntity.ProjectIndex} WHERE ObjectTypePID = @ObjectTypePID  ", new { ObjectTypePID = keyValue });
                }
            }
            catch (Exception ex)
            {
                if (ex is ExceptionEx)
                {
                    throw;
                }
                else
                {
                    throw ExceptionEx.ThrowServiceException(ex);
                }
            }
        }

        /// <summary>
        /// 为某个对象类型，关联新的属性
        /// <param name="objectTypeID">对象类型ID</param>
        /// <summary>
        /// <returns></returns>
        public void SaveEntity(string objectTypeID, List<ec_objecttypepEntity> entityList, string ProjectId)
        {

            try
            {
                var projEntity = _projectRepository.GetById(ProjectId);
                //var tableName = ProjectSugar.TableName<ec_objecttypeEntity>(projEntity.ProjectIndex.ToString());
                var objecttypepTableName = ProjectSugar.TableName<ec_objecttypepEntity>(projEntity.ProjectIndex.ToString());

                var count = _objecttypepRepository.AsDeleteable().AS(objecttypepTableName).Where(t => t.ObjectTypeID == objectTypeID).ExecuteCommand();//为什么要删？（估计是因为网页里传进来的是全部，而不是增补）
                _objecttypepRepository.AsInsertable(entityList).AS(objecttypepTableName).ExecuteCommand();

                SqlSugarHelper.Db.BeginTran();
                #region 影响已存在的位号（同步加入新增的属性）
                var propertyIDs = entityList.Select(x => x.PropertyID).ToList();
                var enginedataTableName = ProjectSugar.TableName<ec_enginedataEntity>(projEntity.ProjectIndex.ToString());
                var enginedataPropertyTableName = ProjectSugar.TableName<ec_enginedata_propertyEntity>(projEntity.ProjectIndex.ToString());
                var propertyTableName = ProjectSugar.TableName<ec_propertyEntity>(projEntity.ProjectIndex.ToString());

                var query =
                    SqlSugarHelper.Db.Queryable<ec_enginedataEntity>().AS(enginedataTableName)
                    .InnerJoin<ec_objecttypepEntity>((a, b) => a.ObjectTypeID == b.ObjectTypeID)
                    .AS<ec_objecttypepEntity>(objecttypepTableName)
                    .InnerJoin<ec_propertyEntity>((a, b, c) => b.PropertyID == c.PropertyID)
                    .AS<ec_propertyEntity>(propertyTableName)
                    .LeftJoin<ec_enginedata_propertyEntity>((a, b, c, d) => a.EngineDataID == d.EngineDataID
                    && c.PropertyName == d.PropertyName).AS<ec_enginedata_propertyEntity>(enginedataPropertyTableName)
                    .Where((a, b, c, d) => a.ObjectTypeID == objectTypeID && propertyIDs.Contains(b.PropertyID) && d.EngineDataID == null)
                    .Select((a, b, c) => new
                    {
                        a.EngineDataID,
                        c.PropertyName,
                        c.DefaultValue,
                        c.DefaultUnit
                    }).ToList();

                var unitTableName = ProjectSugar.TableName<ec_measuring_unitEntity>(projEntity.ProjectIndex.ToString());
                var units = _unitRepository.AsQueryable().AS(unitTableName).ToList();
                var properties =
                    (from a in query
                     join b in units on a.DefaultUnit equals b.MeasuringUnitID into lb
                     from b in lb.DefaultIfEmpty()
                     select new ec_enginedata_propertyEntity
                     {
                         EngineDataID = a.EngineDataID,
                         PropertyName = a.PropertyName,
                         PropertyValue = a.DefaultValue,
                         MeasuringUnit = b?.MeasuringUnitName,
                         CaseID = "0"
                     }).ToList();
                properties.ForEach(x => x.Create());
                //要不要考虑每个case都加一遍？不加也行。
                //ec_enginedataService.UpdatePixelAndProp里会加

                _enginedataPropertyRepository.AsInsertable(properties).AS(enginedataPropertyTableName).ExecuteCommand();
                #endregion
                SqlSugarHelper.Db.CommitTran();
            }
            catch (Exception ex)
            {
                SqlSugarHelper.Db.RollbackTran();
                if (ex is ExceptionEx)
                {
                    throw;
                }
                else
                {
                    throw ExceptionEx.ThrowServiceException(ex);
                }
            }
        }

        /// <summary>
        /// 保存属性反向关联的对象类型数据（新增）
        /// <param name="propertyID">属性ID</param>
        /// <summary>
        /// <returns></returns>
        public void SavePropertyO(string propertyID, List<ec_objecttypepEntity> entityList, string ProjectId)
        {
            SqlSugarHelper.Db.BeginTran();
            try
            {
                var tableName = ProjectSugar.TableName<ec_objecttypepEntity>(ProjectId);
                _objecttypepRepository.AsDeleteable().AS(tableName).Where(x => x.PropertyID == propertyID).ExecuteCommand();
                _objecttypepRepository.AsInsertable(entityList).AS(tableName).ExecuteCommand();


                var objectTypeIDs = entityList.Select(x => x.ObjectTypeID).ToList();
                var enginedataTableName = ProjectSugar.TableName<ec_enginedataEntity>(ProjectId);
                var propertyTableName = ProjectSugar.TableName<ec_propertyEntity>(ProjectId);
                var enginedataPropertyTableName = ProjectSugar.TableName<ec_enginedata_propertyEntity>(ProjectId);

                var query =
                    SqlSugarHelper.Db.Queryable<ec_enginedataEntity>().AS(enginedataTableName)
                    .InnerJoin<ec_objecttypepEntity>((a, b) => a.ObjectTypeID == b.ObjectTypeID)
                    .AS<ec_objecttypepEntity>(tableName)
                    .InnerJoin<ec_propertyEntity>((a, b, c) => b.PropertyID == c.PropertyID)
                    .AS<ec_propertyEntity>(propertyTableName)
                    .LeftJoin<ec_enginedata_propertyEntity>((a, b, c, d) => a.EngineDataID == d.EngineDataID
                    && c.PropertyName == d.PropertyName).AS<ec_enginedata_propertyEntity>(enginedataPropertyTableName)
                    .Where((a, b, c, d) => objectTypeIDs.Contains(a.ObjectTypeID) && b.PropertyID == propertyID && d.EngineDataID == null)
                    .Select((a, b, c) => new
                    {
                        a.EngineDataID,
                        c.PropertyName,
                        c.DefaultValue,
                        c.DefaultUnit
                    }).ToList();

                var unitTableName = ProjectSugar.TableName<ec_measuring_unitEntity>(ProjectId);
                var units = _unitRepository.AsQueryable().AS(unitTableName).ToList();
                var properties =
                    (from a in query
                     join b in units on a.DefaultUnit equals b.MeasuringUnitID into lb
                     from b in lb.DefaultIfEmpty()
                     select new ec_enginedata_propertyEntity
                     {
                         EngineDataID = a.EngineDataID,
                         PropertyName = a.PropertyName,
                         PropertyValue = a.DefaultValue,
                         MeasuringUnit = b?.MeasuringUnitName
                     }).ToList();
                properties.ForEach(x => x.Create());
                _enginedataPropertyRepository.AsInsertable(properties).ExecuteCommand();

                SqlSugarHelper.Db.CommitTran();
            }
            catch (Exception ex)
            {
                SqlSugarHelper.Db.RollbackTran();
                if (ex is ExceptionEx)
                {
                    throw;
                }
                else
                {
                    throw ExceptionEx.ThrowServiceException(ex);
                }
            }
        }

        #endregion

    }
}
